using System;
using System.Linq;
using System.Web.Mvc;
using OurWedding1.Models;

namespace OurWedding1.Controllers
{
    [Authorize]
    public class GuestInExpensesController : BaseController
    {
        private readonly IGuestRepository _guestRepository;
        private readonly IExpenseRepository _expenseRepository;
        private readonly IGuestInExpenseRepository _guestinexpenseRepository;
        private readonly IGuestGroupRepository _guestGroupRepository = new GuestGroupRepository(); //TODO:IoC

        private IQueryable<Guest> GetPossibleGuests()
        {
            if (SelectedWeddingId == null)
            {
                throw new ArgumentNullException();
            }
            return _guestRepository.All
                .Where(d => d.GuestGroup.WeddingId == SelectedWeddingId)
                .OrderBy(g => g.GuestGroup.GuestSideId)
                .ThenBy(g => g.GuestGroup.Name)
                .ThenBy(g => g.LastName)
                .ThenBy(g => g.FirstName);
        }

        private IQueryable<Guest> GetPossibleGuests(GuestGroup group)
        {
            if (group == null)
            {
                throw new ArgumentNullException();
            }
            return GetPossibleGuests().Where(g => g.GuestGroupId == group.GuestGroupId);
        }

        private IQueryable<Expense> GetPossibleExpenses()
        {
            if (SelectedWeddingId == null)
            {
                throw new ArgumentNullException();
            }
            return _expenseRepository.All
                .Where(e => e.WeddingId == SelectedWeddingId)
                .Where(e => e.ExpenseType.isProPerson)
                                .OrderBy(g => g.ExpenseCategory.Name)
                                .ThenBy(e => e.Name);
        }

        private bool EntityExists(GuestInExpense entity)
        {
            return _guestinexpenseRepository.All
                .Any(d => d.ExpenseId == entity.ExpenseId && d.GuestId == entity.GuestId);
        }

        // If you are using Dependency Injection, you can delete the following constructor
        public GuestInExpensesController()
            : this(new GuestRepository(), new ExpenseRepository(), new GuestInExpenseRepository())
        {
        }

        public GuestInExpensesController(IGuestRepository guestRepository, IExpenseRepository expenseRepository, IGuestInExpenseRepository guestinexpenseRepository)
        {
            _guestRepository = guestRepository;
            _expenseRepository = expenseRepository;
            _guestinexpenseRepository = guestinexpenseRepository;
        }



        public ActionResult IndexByExpense(int id)
        {
            var expense = _expenseRepository.Find(id);
            if (!SelectedWeddingId.HasValue || expense == null)
            {
                return Content(""); //TODO:Error introduce
            }

            var model = _guestinexpenseRepository.AllIncluding(guestinexpense => guestinexpense.Guest);
            model = model.Where(t => t.Expens.WeddingId == SelectedWeddingId.Value).Where(t => t.ExpenseId == id); //TODO:Do some test
            model = model.OrderByDescending(t => t.Discount);
            return PartialView("_IndexByExpense", model);
        }

        public ActionResult IndexByGuestGroup(int id)
        {
            var group = _guestGroupRepository.Find(id);
            if (!SelectedWeddingId.HasValue || group == null)
            {
                return Content(""); //TODO:Error introduce
            }
            if (group.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error introduce
            }

            var model = _guestinexpenseRepository.AllIncluding(guestinexpense => guestinexpense.Guest);
            model = model.Where(d => d.Guest.GuestGroupId == group.GuestGroupId);
            if (!model.Any())
            {
                ViewBag.InfoTitle = "";
                ViewBag.InfoField = Resources.OutOfData;
                return PartialView("_UiHighlight");
            }
            model = model.OrderByDescending(t => t.Discount);
            return PartialView("_IndexByGuestGroup", model);
        }


        //id = expenseId
        public ActionResult CreateByExpense(int id)
        {
            var expense = _expenseRepository.Find(id);
            if (!SelectedWeddingId.HasValue || expense == null)
            {
                return Content(""); //TODO:Error Introduce
            }
            if (expense.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error Introduce
            }
            var model = new GuestInExpense { ExpenseId = expense.ExpenseId };
            ViewBag.PossibleGuests = GetPossibleGuests();

            return PartialView("_CreateByExpense", model);
        }

        [HttpPost]
        public ActionResult CreateByExpense(GuestInExpense model)
        {
            if (EntityExists(model))
            {
                ModelState.AddModelError("b", Resources.EntityExists);
            }
            if (ModelState.IsValid)
            {
                // validation of the modal view model succeeded =>
                // we return a JSON result containing some precalculated value
                _guestinexpenseRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestinexpenseRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                        {
                            value = "K!"
                        });
                }

                ModelState.AddModelError("a", Resources.ErrorOcured);
            }
            ViewBag.PossibleGuests = GetPossibleGuests();

            return PartialView("_CreateByExpense", model);
        }

        //id = guestgroup
        public ActionResult CreateByGuestGroup(int id)
        {
            var group = _guestGroupRepository.Find(id);
            if (!SelectedWeddingId.HasValue || group == null)
            {
                return Content(""); //TODO:Error Introduce
            }
            if (group.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error Introduce
            }
            var model = new GuestInExpense();
            ViewBag.PossibleGuests = GetPossibleGuests(group);
            ViewBag.PossibleExpenses = GetPossibleExpenses();
            return PartialView("_CreateByGuestGroup", model);
        }

        [HttpPost]
        public ActionResult CreateByGuestGroup(int id,GuestInExpense model)
        {
            if (EntityExists(model))
            {
                ModelState.AddModelError("a",Resources.EntityExists);
            }
            if (ModelState.IsValid)
            {
                // validation of the modal view model succeeded =>
                // we return a JSON result containing some precalculated value
                _guestinexpenseRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestinexpenseRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                    {
                        value = "K!"
                    });
                }

                ModelState.AddModelError("a", Resources.ErrorOcured);
            }
            var group = _guestGroupRepository.Find(id);
            ViewBag.PossibleGuests = @group!= null ? GetPossibleGuests(@group) : GetPossibleGuests();
            
            ViewBag.PossibleExpenses = GetPossibleExpenses();

            return PartialView("_CreateByGuestGroup", model);
        }


        public ActionResult EditByExpense(int id)
        {
            var model = _guestinexpenseRepository.Find(id);
            if (!SelectedWeddingId.HasValue || model == null)
            {
                return Content("");
            }
            if (model.Expens.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error introduce
            }
            ViewBag.PossibleGuests = GetPossibleGuests();
            return PartialView("_EditByExpense", model);
        }

        [HttpPost]
        public ActionResult EditByExpense(GuestInExpense model)
        {
            //if (EntityExists(model))
            //{
            //    ModelState.AddModelError("a", Resources.EntityExists);
            //} //TODO:Improve
            if (ModelState.IsValid)
            {
                // validation of the modal view model succeeded =>
                // we return a JSON result containing some precalculated value
                if (EntityExists(model))
                {
                    ModelState.AddModelError("a", Resources.EntityExists);
                }
                _guestinexpenseRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestinexpenseRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                    {
                        value = "K!"
                    });
                }
                ModelState.AddModelError("a", Resources.ErrorOcured);

            }
            // Validation failed => we need to redisplay the modal form
            // and give the user the possibility to fix his errors
            ViewBag.PossibleGuests = GetPossibleGuests();
            return PartialView("_EditByExpense", model);
        }

        public ActionResult EditByGuestGroup(int id)
        {
            var model = _guestinexpenseRepository.Find(id);
            if (!SelectedWeddingId.HasValue || model == null)
            {
                return Content(""); //TODO:Error introduce
            }
            if (model.Expens.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error introduce
            }
            var guest = _guestRepository.Find(model.GuestId);
            ViewBag.PossibleGuests = GetPossibleGuests(guest.GuestGroup);
            ViewBag.PossibleExpenses = GetPossibleExpenses();
            return PartialView("_EditByGuestGroup", model);
        }

        [HttpPost]
        public ActionResult EditByGuestGroup(int id,GuestInExpense model)
        {
            var discount = _guestinexpenseRepository.Find(id);
            if (ModelState.IsValid)
            {
                //if (EntityExists(model))
                //{
                //    ModelState.AddModelError("a", Resources.EntityExists);
                //    ViewBag.PossibleGuests = discount != null ? GetPossibleGuests(discount.Guest.GuestGroup) : GetPossibleGuests();
                //    ViewBag.PossibleExpenses = GetPossibleExpenses();
                //    return PartialView("_EditByGuestGroup", model);
                //}//TODO:Improve
                // validation of the modal view model succeeded =>
                // we return a JSON result containing some precalculated value
                _guestinexpenseRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestinexpenseRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                    {
                        value = "K!"
                    });
                }
                ModelState.AddModelError("a", Resources.ErrorOcured);

            }
            // Validation failed => we need to redisplay the modal form
            // and give the user the possibility to fix his errors
            ViewBag.PossibleGuests = discount != null ? GetPossibleGuests(discount.Guest.GuestGroup) : GetPossibleGuests();
            ViewBag.PossibleExpenses = GetPossibleExpenses();
            return PartialView("_EditByGuestGroup", model);
        }


        [HttpPost]
        public ActionResult DeleteAjax(int id)
        {
            var model = _guestinexpenseRepository.Find(id);
            if (!SelectedWeddingId.HasValue || model == null)
            {
                return Json(new
                {
                    value = "nok"
                });
            }
            if (model.Expens.WeddingId != SelectedWeddingId.Value)
            {
                return Json(new
                {
                    value = "nok"
                });
            }
            _guestinexpenseRepository.Delete(id);
            bool succeded;
            try
            {
                _guestinexpenseRepository.Save();
                succeded = true;
            }
            catch (Exception)
            {
                succeded = false;
            }

            if (succeded)
            {
                return Json(new
                {
                    value = "ok"
                });
            }
            return Json(new
            {
                value = "nok"
            });
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _guestRepository.Dispose();
                _expenseRepository.Dispose();
                _guestinexpenseRepository.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

